package com.kaba.security.webconfig;

import com.kaba.security.handler.*;
import com.kaba.xtzhgl.service.serviceImpl.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;


/**
 * @Author lvmengjie
 * @Date 2021/3/20
 * @Description Security配置类
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    UserDetailsServiceImpl userDetailsServiceimpl;

    /**
     *  登录成功
     * */
    @Autowired
    LonginsuccessHandler longinsuccessHandler;

    /**
     *  权限拒绝处理逻辑】
     * */
    @Autowired
    CustomAccessDeniedHandler accessDeniedHandler;


    /**
     * 账号被挤下线处理逻辑
     * */
    @Autowired
    CustomizeSessionInformationExpiredStrategy sessionInformationExpiredStrategy;

    /**
     *  登录失败处理逻辑
     * */
    @Autowired
    CustomizeAuthenticationFailureHandler authenticationFailureHandler;

    /**
     * 登出
     * */
    @Autowired
    CustomizeLogoutSuccessHandler logoutSuccessHandler;

    /**
     *  匿名用户访问无权限资源时的异常
     * */
    @Autowired
    CustomizeAuthenticationEntryPoint authenticationEntryPoint;

    /**
     * 安全数据源
     * */
    @Autowired
    CustomizeFilterInvocationSecurityMetadataSource securityMetadataSource;
    /**
     * 决策管理器
     * */
    @Autowired
     CustomizeAccessDecisionManager accessDecisionManager;




    @Bean
    public UserDetailsService userDetailsService() {
        //获取用户账号密码及权限信息
        return new UserDetailsServiceImpl();


    }


    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        // 设置默认的加密方式（强hash方式加密）
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsServiceimpl).passwordEncoder(passwordEncoder());

    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests()//鉴权
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O o) {
                        o.setAccessDecisionManager(accessDecisionManager);//访问决策管理器
                        o.setSecurityMetadataSource(securityMetadataSource);//安全元数据源
                        return o;
                    }
                })
                .antMatchers("/login")
                .permitAll()
                .anyRequest().authenticated().
        //登入
        and().formLogin().
                permitAll().//允许所有用户
                //登录成功处理逻辑
                successHandler(longinsuccessHandler)
                //登录失败处理逻辑
                .failureHandler(authenticationFailureHandler)
                //设置自己的登录界面（如果不设置，将会是自带的登录界面这里我们使用自定义的登录界面）
                .loginPage("http://localhost:9528/#/login")
                //表单提交的url
                .loginProcessingUrl("/user/login").
                //异常处理(权限拒绝、登录失效等)
         and().exceptionHandling().
                //权限拒绝处理逻辑
                accessDeniedHandler(accessDeniedHandler).
                //匿名用户访问无权限资源时的异常处理
                authenticationEntryPoint(authenticationEntryPoint).
         and().//登出
                logout().
                permitAll().//允许所有用户
                //登出的url
                logoutUrl("/user/logout").
                //登出成功处理逻辑
                logoutSuccessHandler(logoutSuccessHandler).
                //登出之后删除cookie
                deleteCookies("JSESSIONID").
         and().//限制登录用户数量
                sessionManagement().
                maximumSessions(2).
                //会话信息过期策略会话信息过期策略(账号被挤下线);
                expiredSessionStrategy(sessionInformationExpiredStrategy);
        http.cors().and().csrf().disable();
    }
}
